package cn.yeziji.forum.service.abstruct;

import cn.yeziji.forum.common.key.CommentCacheKey;
import cn.yeziji.forum.common.key.DetailsCacheKey;
import cn.yeziji.forum.common.key.UserCacheKey;
import cn.yeziji.forum.common.key.WebsocketCacheKey;
import cn.yeziji.forum.utils.CacheUtils;
import com.github.benmanes.caffeine.cache.Cache;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 缓存实例化
 *
 * @author gzkemays
 * @since 2022/4/20 8:16
 */
public abstract class CacheInstance {
  protected CacheUtils cacheUtils;
  protected Map<String, List<String>> cacheKeys = new ConcurrentHashMap<>();
  protected Map<String, List<String>> hashCacheKeys = new ConcurrentHashMap<>();

  String cacheFieldSpiltComma = "::";
  String hashPrefix = "Hash-";
  List<String> cachePrefixKeys =
      new ArrayList<String>() {
        {
          add(CommentCacheKey.DETAIL_COMMENT_CACHE_KEY);
          add(DetailsCacheKey.CACHE_SAVE_KEY);
          add(UserCacheKey.COMMON_USER_PREFIX);
          add(WebsocketCacheKey.COMMON_CHAT_ROOM);
        }
      };

  protected void newInstance(Cache<String, Object> cache) {
    this.cacheUtils = new CacheUtils();
    this.cacheUtils.newCaffeineCache(cache);
  }

  protected void put(String key, Object value, long time, TimeUnit timeUnit) {
    addCacheKeys(key);
    cacheUtils.set(key, value, time, timeUnit);
  }

  protected void remove(String key) {
    cacheUtils.remove(key);
    removeCacheKeys(key);
  }

  protected void putHash(String key, String hashKey, Object value, long time, TimeUnit timeUnit) {
    addCacheHashKey(key, hashKey);
    cacheUtils.setHash(key, hashKey, value, time, timeUnit);
  }

  private String getKeyPrefix(String key) {
    int index = key.indexOf(cacheFieldSpiltComma);
    return key.substring(0, index);
  }

  /**
   * 保存通用前缀 -- 缓存键值列表
   *
   * <ul>
   *   将键值的前缀作为获取，缓存键值列表的依据
   *   <li>那么后续我们需要获取有关键值时则不需要通过全遍历的方式获取，而是采用更小的区间。
   * </ul>
   *
   * @param key key -> Prefix :: Cache Key
   */
  private void addCacheKeys(String key) {
    String prefix = getKeyPrefix(key);
    List<String> keys = getKeys(prefix, key);
    keys.add(key);
    cacheKeys.put(prefix, keys);
  }

  private void removeCacheKeys(String key) {
    String prefix = getKeyPrefix(key);
    List<String> keys = getKeys(prefix, key);
    if (!keys.isEmpty()) {
      keys.remove(key);
    }
    cacheKeys.put(prefix, keys);
  }

  private void addCacheHashKey(String key, String hashKey) {
    String prefix = getKeyPrefix(key);
    List<String> keys = getKeys(prefix, key);
    if (!keys.isEmpty()) {
      keys.remove(key);
    }
    hashCacheKeys.put(prefix, keys);
  }

  private List<String> getKeys(String prefix, String key) {
    List<String> keys = cacheKeys.get(prefix);
    if (CollectionUtils.isEmpty(keys)) {
      keys = new ArrayList<>();
    }
    return keys;
  }

  public static void main(String[] args) {
    String text = "abc::asd";

    System.out.println(text.substring(0, text.indexOf("::")));
  }
}
